package com.telit.android.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.telit.android.dao.AppPatrolTrackDao;
import com.telit.android.dao.AppTaskDao;
import com.telit.android.dao.CommEventTaskTrackDao;
import com.telit.android.dto.AppTrackDTO;
import com.telit.android.entity.AppPatrolTrack;
import com.telit.android.service.IAppPatrolTrackService;
import com.telit.android.util.PatrolInfoUtil;
import com.telit.common.constant.RoleCodeConstants;
import com.telit.common.core.utils.FeignUtils;
import com.telit.common.entity.AppTask;
import com.telit.common.entity.CommEventTaskTrack;
import com.telit.common.entity.DataReturn;
import com.telit.common.entity.PageData;
import com.telit.common.enums.ResultCode;
import com.telit.common.exception.ForestBaseException;
import com.telit.common.util.TimeUtils;
import com.telit.firecommand.feign.RemoteFirecommandService;
import com.telit.firecommand.vo.ForesterVO;
import com.telit.upms.feign.RemoteUpmsService;
import com.telit.upms.vo.MicroSysUserAllInfoVo;
import com.telit.upms.vo.MicroSysUserVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @Auther amy
 * @Describe
 */
@Service
@RequiredArgsConstructor
public class AppPatrolTrackServiceImpl extends ServiceImpl<AppPatrolTrackDao, AppPatrolTrack> implements IAppPatrolTrackService {

    @Autowired
    private AppTaskDao appTaskDao;

    @Autowired
    private AppPatrolTrackDao appPatrolTrackDao;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private RemoteFirecommandService remoteFirecommandService;


    @Resource
    private CommEventTaskTrackDao commEventTaskTrackDao;

    @Resource
    private RemoteUpmsService remoteUpmsService;

    @Override
    public int add(AppPatrolTrack appPatrolTrack) {
        // 判断巡护记录是否重复提交(同一个护林员同一个时间段,对于同一个类型的巡护类型只能有一个)
        if (!CollectionUtils.isEmpty(baseMapper.listByConditionNoPage(appPatrolTrack))) {
            return 1;
        }
        String status = "3";
        Long taskId = appPatrolTrack.getTaskId();
        Long forestkeeperId = appPatrolTrack.getProtectorId();
        //更新任务组开始时间
    /*    appTaskDao.update(new AppTask().setStartTime(appPatrolTrack.getStartTime()),
                new QueryWrapper<AppTask>().eq("id",appPatrolTrack.getTaskId()).isNull("start_time"));*/
        // 上传轨迹的时候,set轨迹id到子任务表中，并修改子任务状态
        commEventTaskTrackDao.update(new CommEventTaskTrack().setTrackId(appPatrolTrack.getId()).setStatus(status),
                new QueryWrapper<CommEventTaskTrack>().eq("task_id", appPatrolTrack.getTaskId()).eq("forestkeeper_id", appPatrolTrack.getProtectorId()));

        if ("1".equals(appPatrolTrack.getPatrolType()) || "7".equals(appPatrolTrack.getPatrolType())) {
            // 修改主任务状态
            appTaskDao.update(new AppTask().setStatus(status).setFinishTime(appPatrolTrack.getEndTime()).setEndTime(appPatrolTrack.getEndTime()),
                    new QueryWrapper<AppTask>().eq("id", appPatrolTrack.getTaskId()));
        } else {
            //修改主任务表状态
            List<Long> commEventTaskTrackIdList = commEventTaskTrackDao.selectIdByTaskIdAndStatus(taskId, status, forestkeeperId);
            if (CollectionUtils.isEmpty(commEventTaskTrackIdList)) {
                appTaskDao.update(new AppTask().setStatus(status).setFinishTime(appPatrolTrack.getEndTime()),
                        new QueryWrapper<AppTask>().eq("id", appPatrolTrack.getTaskId()));
            }
        }
        return baseMapper.insert(appPatrolTrack);
    }

    @Override
    public List<AppPatrolTrack> listByProtectorId(AppPatrolTrack appPatrolTrack) {
        return baseMapper.listByConditionNoPage(appPatrolTrack);
    }

    @Override
    public PageData<List<AppPatrolTrack>> queryPatrolTrackRecord(Integer current, Integer size, Long protectorId,
                                                                 String startTime, String endTime) {
        IPage<AppPatrolTrack> iPage = new Page<>(current, size);
        IPage<AppPatrolTrack> pages = appPatrolTrackDao.queryPatrolTrackRecord(iPage, protectorId, startTime, endTime);
        List<AppPatrolTrack> records = pages.getRecords();
        //2022-05-18 对于旧代码中 获取 用户信息地方进行变更 -----fixed by yzx------start
       /* records.forEach(e -> {
            Long id = e.getProtectorId();
            SysUserDetailVo userInfo = userInfoService.getUserInfo(id);
            if (userInfo != null) {
                e.setProtectorName(userInfo.getRealName());
            }
            //20220415 对时间duration 进行处理
            e.setDuration(Convert.toStr(DateUtil.between(e.getStartTime(), e.getEndTime(), DateUnit.MINUTE)));
            e.setDistance(NumberUtil.roundHalfEven(NumberUtil.toBigDecimal(e.getDistance()).divide(NumberUtil.toBigDecimal("1000")), 3).toPlainString());
        });*/

        final List<Long> ids = records.parallelStream()
                //过滤掉空 id
                .filter(dto -> ObjectUtil.isNotNull(dto.getProtectorId()))
                .map(AppPatrolTrack::getProtectorId)
                //id 去重
                .distinct()
                .collect(Collectors.toList());

        com.telit.common.core.utils.Result<Map<Long, MicroSysUserVo>> selectByBatchIdsResult = remoteUpmsService.selectByBatchIds(
                ids, true);
        Map<Long, MicroSysUserVo> microSysUserVoMap = FeignUtils.unwrap(selectByBatchIdsResult);
        records.forEach(e -> {
            //对于userMap 中能够取到的给值，取不到给空字符串
            e.setProtectorName(microSysUserVoMap.get(Convert.toLong(e.getId())) != null ? microSysUserVoMap.get(
                    Convert.toLong(e.getId())).getRealName() : "");
            e.setDuration(Convert.toStr(DateUtil.between(e.getStartTime(), e.getEndTime(), DateUnit.MINUTE)));
            e.setDistance(NumberUtil.roundHalfEven(
                    NumberUtil.toBigDecimal(e.getDistance()).divide(NumberUtil.toBigDecimal("1000")),
                    3).toPlainString());
        });
        //2022-05-18 对于旧代码中 获取 用户信息地方进行变更 -----fixed by yzx------end

        return PageData.<List<AppPatrolTrack>>builder()
                .datas(records)
                .count((int) pages.getTotal())
                .current((int) pages.getCurrent())
                .size((int) pages.getSize())
                .build();
    }

    @Override
    public AppTrackDTO queryDetailById(Long subTaskId, Long protectorId) {
        AppTrackDTO appTrackDTO = appPatrolTrackDao.queryDetailById(subTaskId, protectorId);
        //2022-05-18 优化 避免过度请求 -------fixed by yzx-------start
        //添加姓名
     /*   Long createPersonId = appTrackDTO.getCreatePersonId();
        SysUserDetailVo createPerson = userInfoService.getUserInfo(createPersonId);
        appTrackDTO.setCreatePersonName(createPerson.getRealName());
        Long forestkeeperId = appTrackDTO.getForestkeeperId();
        SysUserDetailVo executePerson = userInfoService.getUserInfo(forestkeeperId);
        appTrackDTO.setForestkeeperName(executePerson.getRealName());*/

        final Long createPersonId = appTrackDTO.getCreatePersonId();
        final Long forestKeeperId = appTrackDTO.getForestkeeperId();
        final List<MicroSysUserAllInfoVo> dbUsers = userInfoService.queryUserInfoByIds(
                CollUtil.newArrayList(createPersonId, forestKeeperId));
        final Map<Long, String> userRealNameMapping = Maps.newHashMap();
        if (CollUtil.isNotEmpty(dbUsers)) {
            userRealNameMapping.putAll(dbUsers.stream().collect(
                    Collectors.toMap(MicroSysUserAllInfoVo::getId, MicroSysUserAllInfoVo::getRealName, (e1, e2) -> e1)));
        }
        appTrackDTO.setCreatePersonName(
                ObjectUtil.defaultIfNull(userRealNameMapping.get(createPersonId), StrUtil.EMPTY));
        appTrackDTO.setForestkeeperName(
                ObjectUtil.defaultIfNull(userRealNameMapping.get(forestKeeperId), StrUtil.EMPTY));

        //2022-05-18 优化 避免过度请求 ------fixed by yzx--------end

        //判断是否逾期
        if (PatrolInfoUtil.isDelay(appTrackDTO.getEndTime(), appTrackDTO.getTaskEndTime())) {
            appTrackDTO.setIsDelay(1);
        } else {
            appTrackDTO.setIsDelay(0);
        }
        //添加巡护路径
        PatrolInfoUtil.setDistantAndDurationAndPointCollection(appTrackDTO, appTrackDTO.getForestkeeperId(),
                appTrackDTO.getTaskId());
        if (appTrackDTO.getTaskStartTime() != null && appTrackDTO.getTaskEndTime() != null) {
            appTrackDTO.setDuration(Convert.toStr(
                    DateUtil.between(appTrackDTO.getTaskStartTime(), appTrackDTO.getTaskEndTime(), DateUnit.MINUTE)));
        }
        //停留时长
        if (StrUtil.isNotEmpty(appTrackDTO.getPauseDuration())) {
            appTrackDTO.setPauseDuration(TimeUtils.secondsToMinutes(appTrackDTO.getPauseDuration()));
        }
        return appTrackDTO;
    }

    @Override
    public PageData<Object> queryPatrolTrackRecordForRealName(Integer current, Integer size, String districtCode,
                                                              String realName, String startTime, String endTime) {
        final List<Long> forestKeeperIds = CollUtil.newArrayList();
        List<ForesterVO> userList = new ArrayList<>();

        //根据名称查询人员
        DataReturn<PageData<List<ForesterVO>>> qryUserListDataReturn = remoteFirecommandService.qryUserList(realName,
                null, districtCode, true, RoleCodeConstants.ROLE_CODE_FORESTER, null, 1, Integer.MAX_VALUE);
        if (!ResultCode.SUCCESS.getCode().equals(qryUserListDataReturn.getCode())) {
            throw new ForestBaseException(qryUserListDataReturn.getErrorMsg());
        }
        List<Long> idList = qryUserListDataReturn.getData().getDatas().stream().map(
                foresterVO -> Convert.toLong(foresterVO.getId())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(idList)) {
            forestKeeperIds.addAll(idList);
            userList = qryUserListDataReturn.getData().getDatas();
        } else {
            return doPageData(new Page<>(current, size));
        }

        final IPage<AppPatrolTrack> pages = appPatrolTrackDao.queryPatrolTrackRecordWithFuzzyName(
                new Page<>(current, size), forestKeeperIds, startTime, endTime);

        final Map<Long, String> idNameMap = userList.stream().collect(
                Collectors.toMap(ForesterVO::getId, ForesterVO::getRealName, (e1, e2) -> e1));
        if (MapUtil.isEmpty(idNameMap)) {
            //获取page中 id
            final List<Long> ids = pages.getRecords().stream()
                    .filter(apt -> ObjectUtil.isNotNull(apt.getProtectorId()))
                    .map(AppPatrolTrack::getProtectorId)
                    .distinct()
                    .collect(Collectors.toList());
            //ids 为空不查询
            if (CollUtil.isNotEmpty(ids)) {
                final List<MicroSysUserAllInfoVo> vos = userInfoService.queryUserInfoByIds(ids);
                if (CollUtil.isNotEmpty(vos)) {
                    idNameMap.putAll(vos.stream().collect(
                            Collectors.toMap(MicroSysUserAllInfoVo::getId, MicroSysUserAllInfoVo::getRealName, (e1, e2) -> e1)));
                }
            }
        }

        pages.getRecords().forEach(e -> {
            e.setProtectorName(ObjectUtil.defaultIfNull(idNameMap.get(e.getProtectorId()), e.getProtectorName()));
            e.setDuration(Convert.toStr(DateUtil.between(e.getStartTime(), e.getEndTime(), DateUnit.MINUTE)));
            e.setDistance(NumberUtil.roundHalfEven(NumberUtil.toBigDecimal(e.getDistance()).divide(NumberUtil.toBigDecimal("1000")), 3).toPlainString());
        });
        return doPageData(pages);
    }

    private PageData<Object> doPageData(IPage<AppPatrolTrack> pages) {
        //代码cv 操作
        final PageData<Object> pageData = new PageData<>();
        pageData.setDatas(pages.getRecords());
        pageData.setCount((int) pages.getTotal());
        pageData.setCurrent((int) pages.getCurrent());
        pageData.setSize((int) pages.getSize());
        return pageData;
    }
}
